package com.stockz.ui.swing.charting.decorator;

import com.stockz.ui.swing.charting.display.Displayable;
import com.stockz.ui.swing.charting.display.indicator.AbstractDisplayableIndicatorConfiguration;
import com.stockz.ui.swing.charting.display.indicator.SimpleMovingAverage;
import com.stockz.ui.swing.charting.display.indicator.Value;
import com.stockz.ui.swing.charting.util.MathUtil;
import com.stockz.ui.swing.charting.util.UIChartingConstant;
import com.stockz.ui.swing.charting.util.UIChartingConstant.OVERLAY;
import com.stockz.ui.swing.charting.view.StockChartPanel;
import com.stockz.ui.swing.charting.view.StockChartPanelState;
import com.stockz.ui.swing.charting.view.StockChartPanelStructure;
import com.stockz.ui.swing.charting.view.StockRectangle;

public class StockChartPanelIndicatorLayoutDecorator {

	public static void decorate(StockChartPanel stockChartPanel) {
		StockChartPanelState state = stockChartPanel.getStockChartPanelState();
		StockChartPanelStructure structure = stockChartPanel.getStockChartPanelStructure();
		StockRectangle chartRectangle = state.getChartRectangle();
		StockRectangle priceRectangle = state.getPriceRectangle();
		StockRectangle drawingRectangle = state.getDrawingRectangle();
		StockRectangle volumeRectangle = state.getVolumeRectangle();
		
		state.getStockRectangleSet().clear();
		//Calculate available height for chart painting after indicators painting
		if ( state.getDisplayableSet() != null && ! state.getDisplayableSet().isEmpty()) {
			//Need to clear rectangle for all indicator displays
			for (Displayable indicatorDisplay :  state.getDisplayableSet()) {
				StockRectangle r = indicatorDisplay.getRectangle();
				if(chartRectangle.equals(r)
						|| volumeRectangle.equals(r)
						|| drawingRectangle.equals(r)
						|| priceRectangle.equals(r)
						|| r == null){
					continue;
				}
				r.x = 0;
				r.y = 0;
				r.width = 0;
				r.height = 0;
				indicatorDisplay.setRectangle(r);
			}
			
			int independentIndicatorCounter = 0;
			for (Displayable indicatorDisplay :  state.getDisplayableSet()) {
				
				if (OVERLAY.INDEPENDENT.equals(indicatorDisplay.getOverlay())) {
					boolean sibling = false;
					
					
				//	if(indicatorDisplay.isOverlappable()){
						//Iterating over the same set in nested loop
						for (Displayable innerIndicatorDisplay :  state.getDisplayableSet()) {
							//Compare with only those who are already processed
							if(!innerIndicatorDisplay.getRectangle().isEmpty()){
								//Special treatment for SMA and value as they can overlap eachother
								//even though they are not of same type
								if(
										
										(
												((innerIndicatorDisplay instanceof SimpleMovingAverage && indicatorDisplay instanceof Value)
												|| (innerIndicatorDisplay instanceof Value && indicatorDisplay instanceof SimpleMovingAverage))
										|| ((innerIndicatorDisplay.getShortName().equalsIgnoreCase(indicatorDisplay.getShortName()))  && innerIndicatorDisplay.isOverlappable() && indicatorDisplay.isOverlappable()))
										&& innerIndicatorDisplay.getBarValueType().equals(indicatorDisplay.getBarValueType())){
											
									innerIndicatorDisplay.getRectangle().getDisplayableSet().add(indicatorDisplay);
									indicatorDisplay.setRectangle(innerIndicatorDisplay.getRectangle());
									sibling = true;
									break;
								}
							}
						}
						if(sibling){
							sibling = false;
							continue;
						}
				//	}
					
					if (structure.isVariableHeight()) {
						indicatorDisplay.getRectangle().setBounds(
								chartRectangle.x,
								chartRectangle.y+ chartRectangle.height+ structure.getIndicatorIndependentHeight()* independentIndicatorCounter,
								chartRectangle.width,
								structure.getIndicatorIndependentHeight());
						indicatorDisplay.getRectangle().getDisplayableSet().add(indicatorDisplay);
						state.getStockRectangleSet().add(indicatorDisplay.getRectangle());
					} else {
						indicatorDisplay.getRectangle().setBounds(
								chartRectangle.x,
								chartRectangle.y+ chartRectangle.height - structure.getIndicatorIndependentHeight(),
								chartRectangle.width,
								structure.getIndicatorIndependentHeight());		
						indicatorDisplay.getRectangle().getDisplayableSet().add(indicatorDisplay);
						state.getStockRectangleSet().add(indicatorDisplay.getRectangle());
						chartRectangle.height -= structure.getIndicatorIndependentHeight();
						volumeRectangle.height -= structure.getIndicatorIndependentHeight();
						priceRectangle.height -= structure.getIndicatorIndependentHeight(); 
					}
					indicatorDisplay.setColor(UIChartingConstant.colorList.get(0));
					independentIndicatorCounter++;
				}
			}

			state.getChartRectangle().setBounds(chartRectangle);
			//state.getVolumeRectangle().setBounds(chartRectangle);
			//state.getVolumeRectangle().setBounds(state.getDrawingRectangle());
			
			//Price and volume overlay indicator rectangle setting after the chart rectangle is calculated
			for (Displayable indicatorDisplay : state.getDisplayableSet()) {
				if (OVERLAY.PRICE.equals(indicatorDisplay.getOverlay())){
					indicatorDisplay.setRectangle(priceRectangle);
					indicatorDisplay.getRectangle().getDisplayableSet().add(indicatorDisplay);
					state.getStockRectangleSet().add(indicatorDisplay.getRectangle());
					indicatorDisplay.getRectangle().setMaximumValueVisible(state.getMaximumPriceVisible());
					indicatorDisplay.getRectangle().setMinimumValueVisible(state.getMinimumPriceVisible());
				}else if(OVERLAY.VOLUME.equals(indicatorDisplay.getOverlay())) {
					indicatorDisplay.setRectangle(volumeRectangle);
					indicatorDisplay.getRectangle().getDisplayableSet().add(indicatorDisplay);
					state.getStockRectangleSet().add(indicatorDisplay.getRectangle());
					indicatorDisplay.getRectangle().setMaximumValueVisible(state.getMaximumVolumeVisible());
					indicatorDisplay.getRectangle().setMinimumValueVisible(state.getMinimumVolumeVisible());
				}
			}
			
			int stockRectanglePosition = 1;
			for(StockRectangle stockRectangle : state.getStockRectangleSet()){
				stockRectangle.setPosition(stockRectanglePosition);
				stockRectanglePosition++;
				int indicatorDisplayCounter = 0;
				double minimumValueVisible = Double.MAX_VALUE;
				double maximumValueVisible = Double.MIN_VALUE;
				for(Displayable indicatorDisplay : stockRectangle.getDisplayableSet()){
					if(indicatorDisplay instanceof AbstractDisplayableIndicatorConfiguration){
						AbstractDisplayableIndicatorConfiguration configuration = 
							(AbstractDisplayableIndicatorConfiguration)indicatorDisplay;
						double max = MathUtil.max(configuration.getValues(),state.getStartIndex(),state.getEndIndex());
						if(maximumValueVisible < max){
							maximumValueVisible = max;
						}
						double min = MathUtil.min(configuration.getValues(),state.getStartIndex(),state.getEndIndex());
						if(minimumValueVisible > min){
							minimumValueVisible = min;
						}
					}
					
					indicatorDisplay.setColor(UIChartingConstant.colorList.get(indicatorDisplayCounter));
					if(volumeRectangle == stockRectangle){
						indicatorDisplay.setOrder(
								chartRectangle.getDisplayableSet().size()
								+ priceRectangle.getDisplayableSet().size()
								+indicatorDisplayCounter);
					}else{
						indicatorDisplay.setOrder(indicatorDisplayCounter);
					}
					indicatorDisplayCounter++;
					
				}
				
				if(chartRectangle.equals(stockRectangle) 
						|| volumeRectangle.equals(stockRectangle)
						|| priceRectangle.equals(stockRectangle)){
					continue;
				}
				stockRectangle.setMaximumValueVisible(maximumValueVisible);
				stockRectangle.setMinimumValueVisible(minimumValueVisible);
			}
		}
	}
}